﻿using System.Linq;
using System.Windows;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Zoombox;

namespace Red.Controls.Diagrams
{
    public class NodeControlZoombox : Zoombox
    {
        #region Properties

        public DiagramViewModel ViewModel { get; set; }

        #endregion Properties

        #region C-tor

        public NodeControlZoombox()
        {
            MinScale = 0.1;
            MaxScale = 2;
            IsZoomToOutsideCanvasEnabled = true;
        }

        #endregion C-tor

        #region Overridden methods

        protected override void GoHome( object sender, ExecutedRoutedEventArgs e )
        {
            ZoomToNodesBounds();
        }

        public override void ZoomTo( double scale, Point relativeTo )
        {
            ZoomTo( scale, relativeTo, false, true );                    // Turn off restrictRelativePointToContent - need for mouse wheel panning outside the canvas
        }

        #endregion Overridden methods

        #region Public methods

        public void ZoomToNodesBounds()
        {
            ZoomTo( GetRectAroundNodes() );
        }

        #endregion Public methods

        #region Private methods

        private Rect GetRectAroundNodes()
        {
            var nodes = ViewModel.Network.Nodes;
            if ( nodes.Count == 0 )
                return Rect.Empty;

            //Setup content size and margin
            ViewModel.ContentWidth = ContentPresenter.ActualWidth;
            ViewModel.ContentHeight = ContentPresenter.ActualHeight;

            var HorizontalMarigin = ContentPresenter.ActualWidth / 8;
            var VerticalMarigin = ContentPresenter.ActualHeight / 8;

            //Finding bounding cords
            var topPos = nodes.Min( item => item.Y );
            var bottomPos = nodes.Max( item => item.Y );
            var leftPos = nodes.Min( item => item.X );
            var rightPos = nodes.Max( item => item.X );

            //Failsafe looking for nodes size
            const double nodeTypicalHeight = 50;
            const double nodeTypicalWidth = 200;
            var bottomNode = nodes.FirstOrDefault( node => node.Y == bottomPos );
            var rightNode = nodes.FirstOrDefault( node => node.X == rightPos );
            var nodeWidth = nodeTypicalWidth;
            var nodeHeight = nodeTypicalHeight;

            if ( rightNode.Size != Size.Empty )
                nodeWidth = rightNode.Size.Width;

            if ( bottomNode.Size != Size.Empty )
                nodeHeight = bottomNode.Size.Height;

            //Apply node size offset
            bottomPos += nodeHeight;
            rightPos += nodeWidth;

            //Apply margin
            topPos -= VerticalMarigin;
            bottomPos += VerticalMarigin;
            leftPos -= HorizontalMarigin;
            rightPos += HorizontalMarigin;

            return new Rect( new Point( leftPos, topPos ), new Point( rightPos, bottomPos ) );
        }

        #endregion Private methods
    }
}